package MULE.Model.Logic;

import java.awt.Color;
import java.awt.event.ActionEvent;

import MULE.Model.*;
import MULE.Model.Panel.*;

/**
 * Module for player configuration logic.
 * 
 * @author jstep
 */
public class PlayerConfigLogic extends MulePresenter {

	/**
	 * An enumeration of this presenter's supported action commands.
	 */
	public enum ActionCommand {
		NEXT
	}

	private Game game;
	private int playerNum;

	/**
	 * Instantiates a new player configuration logic module.
	 * 
	 * @param view
	 *            This presenter's associated view.
	 */
	public PlayerConfigLogic(PlayerConfigPanel view) {
		super(view);
		this.playerNum = 1;
		this.game = MuleDriver.getGame();
		// Listen to the player config panel's next button.
		view.addNextButtonListener(this);
	}

	/**
	 * Adds a new player with given attributes to the game.
	 * 
	 * @param name
	 *            Player's name.
	 * @param race
	 *            Player's race.
	 * @param color
	 *            Player's color.
	 */
	public void addPlayerWithAttributes(int number, String name, Race race,
			Color color) {
		// Create new player.
		Player newPlayer = new Player(number, name, race, color);

		// Initialize inventory based on game difficulty.
		Inventory playerInventory = newPlayer.getInventory();
		playerInventory.add(game.getDifficulty().getStartingAmount());
		// Give initial amount of money based on player race.
		playerInventory.add(Resource.MONEY, race.getStartingMoney());

		// Add player to game.
		try {
			game.addPlayer(newPlayer);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Returns whether or not the given player name can be used.
	 * 
	 * @param name
	 *            The player name.
	 * @return True if the name is okay to use, false otherwise.
	 */
	public boolean playerNameIsAvailable(String name) {
		// Empty string not allowed.
		if (name.equals("")) {
			return false;
		}
		// Duplicate names not allowed.
		for (Player p : game.getPlayers()) {
			if (p.getName().equals(name)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Returns true if all players for the game have been configured, returns
	 * false otherwise.
	 * 
	 * @return True if all players have been configured, false otherwise.
	 */
	public boolean allPlayersConfigured() {
		return playerNum > game.getNumPlayers();
	}

	/**
	 * Tells the application to show the game panel.
	 */
	public void showGamePanelandEnterPropertySelection() {
		// Start property selection.
		MuleDriver.getPropertySelectionLogic().enterPropertySelectionPhase();
		// Show game panel.
		GameLogic gameLogic = MuleDriver.getGameLogic();
		gameLogic.showView();
	}

	/**
	 * For testing purposes only
	 * 
	 * @param g
	 */
	public void setGame(Game g) {
		game = g;
	}

	/**
	 * Event handler. Responds to input from the player configuration panel.
	 * 
	 * @param e
	 *            The event which was fired from the panel.
	 */
	public void actionPerformed(ActionEvent e) {
		// Next button was pressed.
		if (e.getActionCommand().equals(ActionCommand.NEXT.toString())) {
			PlayerConfigPanel pcp = (PlayerConfigPanel) view;
			// Process name field.
			String pName = pcp.getPlayerName();
			if (!playerNameIsAvailable(pName)) {
				MuleDriver.showAlertDialog("Player Configuration",
						"Please pick a different player name.");
				return;
			}
			// Process race field.
			Race pRace = Race.getRace(pcp.getPlayerRace());
			// Process color field.
			Color pColor = PlayerColor.getColor(pcp.getPlayerColor());

			// Make sure all fields have a value.
			if (pName != null && pRace != null && pColor != null) {
				// Remove this player's selected color from available options.
				pcp.removeColorFromList(pcp.getPlayerColor());
				// Add player to game.
				addPlayerWithAttributes(playerNum, pName, pRace, pColor);
				++playerNum;
				// See if more players need to be configured.
				if (allPlayersConfigured()) {
					showGamePanelandEnterPropertySelection();
				} else {
					pcp.resetPlayerConfig(playerNum);
				}
			}
		}
	}
}
